﻿#pragma once

#include "mats_common.h"

RT_PROGRAM void metal()
{
	float3 world_geometric_normal = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, geometric_normal));
	float3 world_shading_normal = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal));
	float3 ffnormal = faceforward(world_shading_normal, -ray.direction, world_geometric_normal);

	float3 hitpoint = ray.origin + t_hit * ray.direction;

	float3 Kd = diffuse_color;
	//make_float3( tex2D(diffuse_map,  texcoord.x, texcoord.y) );

	float z1 = rnd(current_prd.seed);
	float z2 = rnd(current_prd.seed);
	float z3 = powf(fold(z1), 2.0f / (phong_exp + 1.0f));
	float sintheta = sqrtf(1.0f - z3);
	float costheta = sqrtf(z3);
	float phi = (2.0f * M_PIf) * z2;
	float cosphi = cosf(phi) * sintheta;
	float sinphi = sinf(phi) * sintheta;
	float3 v1, v2;
	create_onb(ffnormal, v1, v2);

	float3 h = ffnormal * costheta + v1 * cosphi + v2 * sinphi;

	current_prd.direction = reflect(ray.direction, h);
	if (dot(current_prd.direction, ffnormal) < 0.0) current_prd.direction = current_prd.direction;

	current_prd.attenuation = current_prd.attenuation * Kd;
	current_prd.countEmitted = false;

	float3 Le, L;
	float nDl = 0.f, pdf = 0.f, Ldist;
	float3 result = make_float3(0.0f);

	sample_lights(make_float3(rnd(current_prd.seed), rnd(current_prd.seed), rnd(current_prd.seed)), hitpoint, ffnormal, Le, L, nDl, Ldist, pdf);
	if (nDl > 0.0f)
	{
		PerRayData_pathtrace_shadow shadow_prd;
		shadow_prd.inShadow = false;
		Ray shadow_ray = make_Ray(hitpoint, L, pathtrace_shadow_ray_type, scene_epsilon, Ldist);
		rtTrace(top_object, shadow_ray, shadow_prd);

		if (!shadow_prd.inShadow)
		{
			float3 h = normalize(-ray.direction + shadow_ray.direction);
			float nDotH = dot(ffnormal, h);
			float weight = pdf * powf(max(nDotH, 0.0f), phong_exp) * (phong_exp + 2.0f) / (M_PIf * 2.0f);

			result += Le* weight;
		}
	}
	current_prd.radiance = result;
}

RT_PROGRAM void alloy()
{
	float3 world_geometric_normal = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, geometric_normal));
	float3 world_shading_normal = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal));
	float3 ffnormal = faceforward(world_shading_normal, -ray.direction, world_geometric_normal);

	float3 hitpoint = ray.origin + t_hit * ray.direction;

	float3 Kd = diffuse_color;

	float z1 = rnd(current_prd.seed);
	float z2 = rnd(current_prd.seed);
	float z3 = powf(fold(z1), 2.0f / (phong_exp + 1.0f));
	float sintheta = sqrtf(1.0f - z3);
	float costheta = sqrtf(z3);
	float phi = (2.0f * M_PIf) * z2;
	float cosphi = cosf(phi) * sintheta;
	float sinphi = sinf(phi) * sintheta;
	float3 v1, v2;
	create_onb(ffnormal, v1, v2);

	float3 h = ffnormal * costheta + v1 * cosphi + v2 * sinphi;

	current_prd.direction = reflect(ray.direction, h);
	if (dot(current_prd.direction, ffnormal) < 0.0) current_prd.direction = current_prd.direction;

	current_prd.attenuation = current_prd.attenuation * Kd;
	current_prd.countEmitted = false;

	float3 Le, L;
	float nDl = 0.f, pdf = 0.f, Ldist;
	float3 result = make_float3(0.0f);

	sample_lights(make_float3(rnd(current_prd.seed), rnd(current_prd.seed), rnd(current_prd.seed)), hitpoint, ffnormal, Le, L, nDl, Ldist, pdf);
	if (nDl > 0.0f)
	{
		PerRayData_pathtrace_shadow shadow_prd;
		shadow_prd.inShadow = false;
		Ray shadow_ray = make_Ray(hitpoint, L, pathtrace_shadow_ray_type, scene_epsilon, Ldist);
		rtTrace(top_object, shadow_ray, shadow_prd);

		if (!shadow_prd.inShadow)
		{
			float3 h = normalize(-ray.direction + shadow_ray.direction);
			float nDotH = dot(ffnormal, h);
			float weight = powf(max(nDotH, 0.0f), phong_exp) * (phong_exp + 2.0f) / (M_PIf * 2.0f);
			result += make_float3(rect_envmap_le(ray.direction)) * weight;
		}
	}
	current_prd.radiance = result;
}

RT_PROGRAM void shadow()
{
	if (fmaxf(emission_color) == 0.0f)
	{
		current_prd_shadow.inShadow = true;
		current_prd_shadow.attenuation = make_float3(0.0f);
		rtTerminateRay();
	}
}